﻿#include "serialport.h"

#include "sdk/QsLog/include/QsLog.h"

#include <QDebug>
#include <QTime>
#include <QElapsedTimer>

SerialPort::SerialPort(QSettings *settings, QObject *parent) : QObject(parent),
    m_settings(settings),
    m_serialPort(nullptr)
{
    // 初始化
    init();
}

SerialPort::~SerialPort()
{
    if (m_serialPort != nullptr) {
        m_serialPort->close();
        m_serialPort->deleteLater();
    }
}

QStringList SerialPort::scanSerialPort()
{
    // 实例化一个串口对象
    QSerialPort* serialPort = new QSerialPort;

    QStringList portNameList;
    foreach (const QSerialPortInfo& info, QSerialPortInfo::availablePorts()) {
        // 读取串口信息
        serialPort->setPort(info);
        if (serialPort->open(QIODevice::ReadWrite)) {
            // 判断串口能否以读写方式打开
            portNameList << serialPort->portName();
            serialPort->close();
        }
    }

    // 删除实例化的串口对象
    serialPort->deleteLater();

    return portNameList;
}

bool SerialPort::isOpen() const
{
    if (m_serialPort != nullptr)
        return m_serialPort->isOpen();

    return false;
}

bool SerialPort::open()
{
    // 设置串口参数
    m_settings->beginGroup("SerialPort");
    QString portName = m_settings->value("portName").toString();
    int baudRate = m_settings->value("baudRate").toInt();
    int dataBits = m_settings->value("dataBits").toInt();
    QString stopBits = m_settings->value("stopBits").toString();
    QString parity = m_settings->value("parity").toString();
    QString flowControl = m_settings->value("flowControl").toString();
    m_settings->endGroup();
    qDebug() << "****serialport open with params:" << portName << baudRate << dataBits << stopBits << parity << flowControl;

    m_serialPort->setPortName(portName);
    m_serialPort->setBaudRate(baudRate);
    m_serialPort->setDataBits(m_dataBitsMap.value(dataBits));
    m_serialPort->setStopBits(m_stopBitsMap.value(stopBits));
    m_serialPort->setParity(m_parityMap.value(parity));
    m_serialPort->setFlowControl(m_flowControlMap.value(flowControl));

    // 打开串口
    if (m_serialPort->open(QSerialPort::ReadWrite)) {
        // 异步方式读取串口数据
        connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPort::onRead);

        return true;
    } else {
        QLOG_ERROR() << "can not open serialport: " << m_serialPort->errorString();
        emit sigErrorOccurred(m_serialPort->errorString());
    }

    return false;
}

void SerialPort::close()
{
    if (m_serialPort != nullptr) {
        m_serialPort->close();
        //m_serialPort->deleteLater();
    }
}

void SerialPort::write(const QByteArray &data)
{
    if (m_serialPort->isOpen()) {
        qint64 count = m_serialPort->write(data);
        if (m_serialPort->waitForBytesWritten(m_writeTimeout)) {
        }
        m_serialPort->flush();

        if (count <= 0) {
            QLOG_ERROR() << "****serialport write failed: " << m_serialPort->errorString();
            emit sigErrorOccurred(m_serialPort->errorString());
        }
    }
}

void SerialPort::clear()
{
    if (m_serialPort != nullptr) {
        m_serialPort->clear();
        m_recvBuffer.clear();
    }
}

QByteArray SerialPort::recvBuffer() const
{
    return m_recvBuffer;
}

void SerialPort::init()
{
    // 创建串口对象
    m_serialPort = new QSerialPort;

    // 数据位
    m_dataBitsMap.insert(5, QSerialPort::Data5);
    m_dataBitsMap.insert(6, QSerialPort::Data6);
    m_dataBitsMap.insert(7, QSerialPort::Data7);
    m_dataBitsMap.insert(8, QSerialPort::Data8);

    // 停止位
    m_stopBitsMap.insert("1", QSerialPort::OneStop);
    m_stopBitsMap.insert("1.5", QSerialPort::OneAndHalfStop);
    m_stopBitsMap.insert("2", QSerialPort::TwoStop);

    // 校验位
    m_parityMap.insert("NoParity", QSerialPort::NoParity);
    m_parityMap.insert("EvenParity", QSerialPort::EvenParity);
    m_parityMap.insert("OddParity", QSerialPort::OddParity);
    m_parityMap.insert("SpaceParity", QSerialPort::SpaceParity);
    m_parityMap.insert("MarkParity", QSerialPort::MarkParity);

    // 流控制
    m_flowControlMap.insert("NoFlowControl", QSerialPort::NoFlowControl);
    m_flowControlMap.insert("HardwareControl", QSerialPort::HardwareControl);
    m_flowControlMap.insert("SoftwareControl", QSerialPort::SoftwareControl);

    // 写入超时
    m_settings->beginGroup("SerialPort");
    m_writeTimeout = m_settings->value("writeTimeout").toInt();
    m_settings->endGroup();
}

void SerialPort::onRead()
{
    QByteArray buffer = m_serialPort->readAll();
    if (!buffer.isEmpty()) {
        //qInfo() << "****serialport read: " << buffer.toHex(' ') << QTime::currentTime().toString("HH:mm:ss.zzz");
        m_recvBuffer.append(buffer);
        //emit sigReadFinished(buffer);
    }
}

